package pe.com.bbva.ge.persistencia.orm.hibernate;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import pe.com.bbva.ge.domain.base.Identificador;
import pe.com.bbva.ge.domain.configuracion.Atm;
import pe.com.bbva.ge.domain.configuracion.Casetera;
import pe.com.bbva.ge.domain.configuracion.Denominacion;
import pe.com.bbva.ge.domain.configuracion.Lista;
import pe.com.bbva.ge.domain.configuracion.Posicion;
import pe.com.bbva.ge.domain.configuracion.Regla;
import pe.com.bbva.ge.domain.configuracion.Transportadora;
import pe.com.bbva.ge.domain.configuracion.Valor;
import pe.com.bbva.ge.domain.quartz.QrtzCronTriggers;
import pe.com.bbva.ge.domain.quartz.QrtzJobDetails;
import pe.com.bbva.ge.domain.quartz.QrtzTriggers;
import pe.com.bbva.ge.domain.seguridad.Membresia;
import pe.com.bbva.ge.domain.seguridad.Opcion;
import pe.com.bbva.ge.domain.seguridad.Permiso;
import pe.com.bbva.ge.domain.seguridad.Rol;
import pe.com.bbva.ge.domain.solicitud.TipoSolicitud;
import pe.com.bbva.ge.persistencia.orm.ConfiguracionORM;
import pe.com.bbva.ge.persistencia.orm.hibernate.utileria.Busqueda;
import pe.com.bbva.ge.utileria.Constante;
import pe.com.bbva.ge.utileria.UtileriaComun;
import pe.com.bbva.ge.domain.configuracion.Parametro;

@Repository
public class ConfiguracionORMHibernate extends BaseORMHibernate implements ConfiguracionORM {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1069924240377681947L;

	@Autowired
	public ConfiguracionORMHibernate(SessionFactory sessionFactory) {
		super(sessionFactory);
	}

	@Override
	public List<Valor> obtenerValores(String codigoLista) {
		Busqueda filtro = Busqueda.forClass(Valor.class);
		filtro.createAlias("lista", "l");
		filtro.add(Restrictions.eq("l.codigo", codigoLista));
		filtro.add(Restrictions.eq("estado", Valor.CODIGO.REGISTRO_ESTADO_ACTIVO));
		return buscar(filtro);
	}

	@Override
	public List<Denominacion> obtenerDenominaciones(Valor moneda, Valor tipo) {
		Busqueda filtro = Busqueda.forClass(Denominacion.class);
		filtro.createAlias("moneda", "m");
		filtro.add(Restrictions.eq("m.id", moneda.getId()));
		
		filtro.createAlias("tipo", "t");
		if(tipo != null)
		{
			
			filtro.add(Restrictions.eq("t.id", tipo.getId()));
		}
		
		agregarFiltroEstadoActivo(filtro);
		
		filtro.addOrder(Order.asc("t.id"));
		filtro.addOrder(Order.asc("orden"));
		
		return buscar(filtro);
	}

	@Override
	public Valor obtenerValor(String codigoLista, String codigoValor) {
		Valor valor = null;
		
		Busqueda filtro = Busqueda.forClass(Valor.class);
		filtro.createAlias("lista", "l");
		filtro.add(Restrictions.eq("l.codigo", codigoLista));
		filtro.add(Restrictions.eq("codigo", codigoValor));
		
		List<Valor> listaValores = buscar(filtro);
		
		if(listaValores.size() > 0)
		{
			valor = listaValores.get(0);
		}
		
		return valor;
	}

	@Override
	public List<QrtzCronTriggers> buscarCronTriggers(
			QrtzCronTriggers qrtzCronTriggers) {
		Busqueda filtro = Busqueda.forClass(QrtzCronTriggers.class);
		if (qrtzCronTriggers != null) {
			if(qrtzCronTriggers.getTriggerGroup()!=null && StringUtils.isNotBlank(qrtzCronTriggers.getTriggerGroup())){
				filtro.add(Restrictions.ilike("triggerGroup",
							"%" + qrtzCronTriggers.getTriggerGroup() + "%"));
			}
			if(qrtzCronTriggers.getTriggerName()!=null && StringUtils.isNotBlank(qrtzCronTriggers.getTriggerName())){
				filtro.add(Restrictions.ilike("triggerName",
							"%" + qrtzCronTriggers.getTriggerName() + "%"));
			}
			if (qrtzCronTriggers.getCronExpression() != null && StringUtils.isNotBlank(qrtzCronTriggers.getCronExpression())) {
				filtro.add(Restrictions.ilike("cronExpression", "%" + qrtzCronTriggers.getCronExpression() + "%"));
			}
		}
		return buscar(filtro);
	}

	@Override
	public List<QrtzJobDetails> buscarJobDetails(QrtzJobDetails qrtzJobDetails) {
		Busqueda filtro = Busqueda.forClass(QrtzJobDetails.class);
		if (qrtzJobDetails != null) {
			if(qrtzJobDetails.getJobGroup()!=null && StringUtils.isNotBlank(qrtzJobDetails.getJobGroup())){
				filtro.add(Restrictions.ilike("jobGroup",
							"%" + qrtzJobDetails.getJobGroup() + "%"));
			}
			if(qrtzJobDetails.getJobName()!=null && StringUtils.isNotBlank(qrtzJobDetails.getJobName())){
				filtro.add(Restrictions.ilike("jobName",
							"%" + qrtzJobDetails.getJobName() + "%"));
			}
			if (qrtzJobDetails.getDescription() != null && StringUtils.isNotBlank(qrtzJobDetails.getDescription())) {
				filtro.add(Restrictions.ilike("description", "%" + qrtzJobDetails.getDescription() + "%"));
			}
			if (qrtzJobDetails.getJobClassName() != null && StringUtils.isNotBlank(qrtzJobDetails.getJobClassName())) {
				filtro.add(Restrictions.ilike("jobClassName", "%" + qrtzJobDetails.getJobClassName() + "%"));
			}
		}
		return buscar(filtro);
	}

	@Override
	public List<QrtzTriggers> buscarTriggers(QrtzTriggers qrtzTriggers) {
		Busqueda filtro = Busqueda.forClass(QrtzTriggers.class);
		if (qrtzTriggers != null) {
			if(qrtzTriggers.getTriggerGroup()!=null && StringUtils.isNotBlank(qrtzTriggers.getTriggerGroup())){
				filtro.add(Restrictions.ilike("triggerGroup",
							"%" + qrtzTriggers.getTriggerGroup() + "%"));
			}
			if(qrtzTriggers.getTriggerName()!=null && StringUtils.isNotBlank(qrtzTriggers.getTriggerName())){
				filtro.add(Restrictions.ilike("triggerName",
							"%" + qrtzTriggers.getTriggerName() + "%"));
			}
			if (qrtzTriggers.getDescription() != null && StringUtils.isNotBlank(qrtzTriggers.getDescription())) {
				filtro.add(Restrictions.ilike("description", "%" + qrtzTriggers.getDescription() + "%"));
			}
			if (qrtzTriggers.getTriggerType() != null && StringUtils.isNotBlank(qrtzTriggers.getTriggerType())) {
				filtro.add(Restrictions.ilike("triggerType", "%" + qrtzTriggers.getTriggerType() + "%"));
			}
			
			if (qrtzTriggers.getPriority() != null && StringUtils.isNotBlank(qrtzTriggers.getPriority().toString())) {
				filtro.add(Restrictions.eq("priority", qrtzTriggers.getPriority()));
			}
			if (qrtzTriggers.getJobGroup() != null && StringUtils.isNotBlank(qrtzTriggers.getJobGroup())) {
				filtro.add(Restrictions.eq("jobGroup", qrtzTriggers.getJobGroup()));
			}
			if (qrtzTriggers.getJobGroup() != null && StringUtils.isNotBlank(qrtzTriggers.getJobGroup())) {
				filtro.add(Restrictions.eq("jobName", qrtzTriggers.getJobName()));
			}
			if(qrtzTriggers.getTriggerState()!=null && StringUtils.isNotBlank(qrtzTriggers.getTriggerState())){
				filtro.add(Restrictions.ilike("triggerState", "%" + qrtzTriggers.getTriggerState() + "%"));
			}
		}
		return buscar(filtro);
	}

	@Override
	public List<Posicion> obtenerPosicones(Valor TipoOrigenDestino) {
		Busqueda filtro = Busqueda.forClass(Posicion.class);
		filtro.createAlias("tipo", "t");
		
		filtro.add(Restrictions.eq("t.id", TipoOrigenDestino.getId()));
		//filtro.add(Restrictions.eq("estado", "A"));
		return buscar(filtro);
	}

	@Override
	public List<TipoSolicitud> obtenerTipoSolicitud() {
		Busqueda filtro = Busqueda.forClass(TipoSolicitud.class);
		filtro.createAlias("estado", "e");
		filtro.add(Restrictions.eq("e.id", 1L));
		
		return buscar(filtro);
	}

	@Override
	public List<Atm> obtenerListaATM() {
		Busqueda filtro = Busqueda.forClass(Atm.class);
		filtro.createAlias("estado", "e");
		filtro.add(Restrictions.eq("e.id", 1L));
		
		return buscar(filtro);
	}

	@Override
	public List<Casetera> obtenerListaCaseteras(Atm atm) {
		Busqueda filtro = Busqueda.forClass(Casetera.class);
		filtro.createAlias("atm", "a");
		filtro.createAlias("estado", "e");
		filtro.add(Restrictions.eq("a.id", atm.getId()));
		filtro.add(Restrictions.eq("e.id", 1L));
		
		return buscar(filtro);
	}

	@Override
	public <Entidad> Entidad obtenerEntidadPorCodigo(
			Identificador identificador, Class<Entidad> clase) {
		Busqueda filtro = Busqueda.forClass(clase);
		filtro.add(Restrictions.eq("codigo", identificador.getCodigo()));
		List<Entidad> lista = buscar(filtro);
		if(lista.size() > 0)
		{
			return lista.get(0);
		}
		return null;
	}

	@Override
	public List<Transportadora> obtenerListaTransportadoras() {
		Busqueda filtro = Busqueda.forClass(Transportadora.class);
		filtro.createAlias("estado", "e");
		filtro.add(Restrictions.eq("e.id", 1L));
		
		return buscar(filtro);
	}

	@Override
	public List<Lista> buscarListas(Lista lista) {
		Busqueda filtro = Busqueda.forClass(Lista.class);
		if (lista != null) {
			if (lista.getId() > 0) {
				filtro.add(Restrictions.eq("id",lista.getId()));
			}
			if (lista.getCodigo() != null) {
				filtro.add(Restrictions.ilike("codigo",lista.getCodigo(), MatchMode.ANYWHERE));
			}
			if (lista.getNombre() != null) {
				filtro.add(Restrictions.ilike("nombre",lista.getNombre(), MatchMode.ANYWHERE));
			}
			if (lista.getEstado() != null) {
				filtro.add(Restrictions.ilike("estado",lista.getEstado(), MatchMode.ANYWHERE));
			}
			if(lista.getDescripcion()!=null){
				filtro.add(Restrictions.ilike("descripcion", lista.getDescripcion(),MatchMode.ANYWHERE));
			}
		}
		filtro.addOrder(Order.asc("id"));
		return buscar(filtro);
	}
	
	@Override
	public List<Valor> buscarValores(Valor valor) {
		Busqueda filtro = Busqueda.forClass(Valor.class);
		if (valor != null) {
			if (valor.getId() > 0) {
				filtro.add(Restrictions.eq("id",	valor.getId()));
			}
			if (valor.getCodigo() != null) {
				filtro.add(Restrictions.ilike("codigo", valor.getCodigo(), MatchMode.ANYWHERE));
			}
			if (valor.getNombre() != null) {
				filtro.add(Restrictions.ilike("nombre",valor.getNombre(), MatchMode.ANYWHERE));
			}
			if (valor.getOrden() != null) {
				filtro.add(Restrictions.eq("orden",valor.getOrden()));
			}
			if (valor.getEstado() != null) {
				filtro.add(Restrictions.ilike("estado",valor.getEstado(), MatchMode.ANYWHERE));
			}
			if (valor.getLista() != null) {
				filtro.createAlias("lista", "l");
				filtro.add(Restrictions.eq("l.id",valor.getLista().getId()));
				if(valor.getLista().getCodigo()!=null){
					filtro.add(Restrictions.eq("l.codigo",valor.getLista().getCodigo()));
				}				
			}
			if(valor.getDescripcion()!=null){
				filtro.add(Restrictions.ilike("descripcion", valor.getDescripcion(),MatchMode.ANYWHERE));
			}
		}
		filtro.addOrder(Order.asc("id"));
		return buscar(filtro);
	}
	
	@Override
	public Parametro obtenerParametroxCodigo(String codigo) {
		Parametro parametro = null;
		List<Parametro> listaParametros = null;
		Busqueda filtro = Busqueda.forClass(Parametro.class);
		filtro.add(Restrictions.eq("codigo", codigo));
		
		listaParametros = buscar(filtro);
		
		if(listaParametros.size() > 0)
		{
			parametro = listaParametros.get(0);
		}
		
		return parametro;
	}

	@Override
	public List<Opcion> buscarOpciones(Opcion opcion) {
		Busqueda filtro = Busqueda.forClass(Opcion.class);
		if (opcion != null) {
			if (opcion.getId() > 0) {
				filtro.add(Restrictions.ilike("id", String.valueOf(opcion.getId()), MatchMode.ANYWHERE));
			}
		}
		filtro.addOrder(Order.asc("codigo"));
		return buscar(filtro);
	}

	@Override
	public Map<String, List<Opcion>> listarOpciones() {
		Busqueda filtro = Busqueda.forClass(Opcion.class);
		filtro.addOrder(Order.asc("id"));
		filtro.addOrder(Order.asc("padre"));
		filtro.addOrder(Order.asc("orden"));
		
		List<Opcion> opciones = buscar(filtro);
		
		return UtileriaComun.ordenarOpciones(opciones);
	}
	
	@Override
	public List<Parametro> buscarParametros(Parametro parametro) {
		Busqueda filtro = Busqueda.forClass(Parametro.class);
		if (parametro != null) {
			if (parametro.getCodigo() != null) {
				filtro.add(Restrictions.ilike("codigo", parametro.getCodigo(), MatchMode.ANYWHERE));
			}
			if (parametro.getNombre() != null) {
				filtro.add(Restrictions.ilike("nombre", parametro.getNombre(), MatchMode.ANYWHERE));
			}
			if (parametro.getValor() != null) {
				filtro.add(Restrictions.ilike("valor", parametro.getValor(), MatchMode.ANYWHERE));
			}
			if (parametro.getEstado() != null && parametro.getEstado().getNombre() != null) {
				filtro.createAlias("estado", "e");
				filtro.createAlias("e.lista", "l");
				filtro.add(Restrictions.eq("l.codigo", Constante.LISTA.CODIGO.REGISTRO_ESTADO));
				filtro.add(Restrictions.ilike("e.nombre", parametro.getEstado().getNombre(), MatchMode.ANYWHERE));
			}

		}
		filtro.addOrder(Order.asc("codigo"));
		return buscar(filtro);
	}
	
	@Override
	public List<Rol> buscarRoles(Rol rol) {
		Busqueda filtro = Busqueda.forClass(Rol.class);
		if (rol != null) {
			if (rol.getId() > 0) {
				filtro.add(Restrictions.eq("id", rol.getId()));
			}
			if (rol.getCodigo() != null) {
				filtro.add(Restrictions.ilike("codigo", "%" + rol.getCodigo() + "%"));
			}
			if (rol.getNombre() != null) {
				filtro.add(Restrictions.ilike("nombre", "%" + rol.getNombre() + "%"));
			}
//			if (rol.getPadre() != null && rol.getPadre().getNombre() != null) {
//				filtro.createAlias("padre", "p");
//				filtro.add(Restrictions.ilike("p.nombre", "%" + rol.getPadre().getNombre() + "%"));
//			}
			if (rol.getEstado() != null && rol.getEstado().getNombre() != null) {
				filtro.createAlias("estado", "est");
				filtro.add(Restrictions.ilike("est.nombre", "%" + rol.getEstado().getNombre() + "%"));
			}

		}
		filtro.addOrder(Order.asc("id"));
		return buscar(filtro);
	}
	
	@Override
	public List<Permiso> obtenerPermisosXRol(Long idRol, boolean estadoActivo) { 
		Busqueda filtro = Busqueda.forClass(Permiso.class);
		filtro.createAlias("rol", "r");
		filtro.createAlias("opcion", "o");
		filtro.createAlias("o.estado", "oe");		
		filtro.add(Restrictions.eq("oe.codigo", Constante.VALOR.REGISTRO_ESTADO.CODIGO.ACTIVO));
		filtro.add(Restrictions.eq("r.id", idRol));
		if(estadoActivo)
		{
			filtro.createAlias("estado", "e");
			filtro.add(Restrictions.eq("e.codigo", Constante.VALOR.REGISTRO_ESTADO.CODIGO.ACTIVO));
			
		}
		filtro.addOrder(Order.asc("o.padre"));
		filtro.addOrder(Order.asc("o.tipo"));
		filtro.addOrder(Order.asc("o.orden"));
		return buscar(filtro);
	}
	
	@Override
	public List<Rol> obtenerRolesHijo(Rol rol) {
		Busqueda filtro = Busqueda.forClass(Rol.class);
		if (rol != null) {
			if (rol.getId() > 0) {
				filtro.add(Restrictions.ne("id", rol.getId()));
				filtro.createAlias("padre", "p");
				filtro.add(Restrictions.eq("p.id", rol.getId()));
			}
		}
		filtro.addOrder(Order.asc("id"));
		return buscar(filtro);
	}
	
	@Override
	public List<Membresia> buscarMembresias(Membresia membresia) {
		Busqueda filtro = Busqueda.forClass(Membresia.class);
		if (membresia != null) {
			if (membresia.getId() > 0) {
				filtro.add(Restrictions.eq("id",membresia.getId()));
			}
			if (membresia.getTipo() != null
					&& membresia.getTipo().getNombre() != null) {
				filtro.createAlias("tipo", "t");
				filtro.createAlias("t.lista", "lt");
				filtro.add(Restrictions.eq("lt.codigo",
						Constante.LISTA.CODIGO.MEMBRESIA_TIPO));
				filtro.add(Restrictions.ilike("t.nombre", membresia.getTipo().getNombre(), MatchMode.ANYWHERE));
			}
			if (membresia.getValor() != null) {
				filtro.add(Restrictions.ilike("valor", membresia.getValor(), MatchMode.ANYWHERE));
			}
			if (membresia.getEstado() != null
					&& membresia.getEstado().getNombre() != null) {
				filtro.createAlias("estado", "e");
				filtro.createAlias("e.lista", "le");
				filtro.add(Restrictions.eq("le.codigo",
						Constante.LISTA.CODIGO.REGISTRO_ESTADO));
				filtro.add(Restrictions.ilike("e.nombre",membresia.getEstado().getNombre(), MatchMode.ANYWHERE));
			}
			if (membresia.getRol() != null
					&& membresia.getRol().getId() > 0) {
				filtro.createAlias("rol", "r");
				filtro.add(Restrictions.eq("r.id",
						membresia.getRol().getId()));
			}

		}
		filtro.addOrder(Order.asc("id"));
		return buscar(filtro);
	}

	@Override
	public List<Atm> obtenerAtmsPorProveedor(Posicion posicionDestino) {
		Busqueda filtro = Busqueda.forClass(Atm.class);
		filtro.add(Restrictions.eq("proveedor", posicionDestino));
		
		agregarFiltroEstadoActivo(filtro);
		
		return buscar(filtro);
	}

	@Override
	public List<Casetera> obtenerCaseterasPorProveedor(Posicion posicionDestino) {
		Busqueda filtro = Busqueda.forClass(Casetera.class);
		filtro.createAlias("atm", "a");
		filtro.add(Restrictions.eq("a.proveedor", posicionDestino));
		agregarFiltroEstadoActivo(filtro);
		return buscar(filtro);
	}
	
	@Override
	public List<Regla> buscarReglas(Regla regla) {
		Busqueda filtro = Busqueda.forClass(Regla.class);
		if (regla != null) {
			if (regla.getCodigo() != null) {
				filtro.add(Restrictions.ilike("codigo", regla.getCodigo(), MatchMode.ANYWHERE));
			}if (regla.getNombre() != null) {
				filtro.add(Restrictions.ilike("nombre", regla.getNombre(), MatchMode.ANYWHERE));
			}if (regla.getTipo() != null && regla.getTipo().getNombre() != null) {
				filtro.createAlias("tipo", "t");
				filtro.add(Restrictions.ilike("t.nombre", regla.getTipo().getNombre(), MatchMode.ANYWHERE));
			}if (regla.getEstado() != null && regla.getEstado().getNombre() != null) {
				filtro.createAlias("estado", "e");
				filtro.add(Restrictions.ilike("e.nombre", regla.getEstado().getNombre(), MatchMode.ANYWHERE));
			}
		}
		filtro.addOrder(Order.asc("id"));
		return buscar(filtro);
	}
}
